package DCSource.Streams;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import DCSource.Crypt.Security;

public class aSecurityOutputStream extends OutputStream{
	private ByteArrayOutputStream chunk = new ByteArrayOutputStream();
	private OutputStream writer = null;
	private PublicKey key = null;
	private int vmaxSize = 0;
	public aSecurityOutputStream(PublicKey key,OutputStream nextTo) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException{
		this.key = key;
		writer = nextTo;
		vmaxSize = Security.encrypt("a".getBytes(), key).length-11;
	}
	public aSecurityOutputStream(KeyPair keys, OutputStream nextTo) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException{
		key = keys.getPublic();
		writer = nextTo;
		vmaxSize = Security.encrypt("a".getBytes(), keys.getPublic()).length-11;
	}
	public void write(int b) throws IOException {
		chunk.write(new byte[]{(byte) b});
		try{
			sendNext();
		}catch(Exception err){}
	}
	public void write(byte[] b) throws IOException{
		chunk.write(b);
		try{
			sendNext();
		}catch(Exception err){}
	}
	public void write(byte[] b, int off, int len) throws IOException{
		chunk.write(b,off,len);
		try{
			sendNext();
		}catch(Exception err){}
	}
	private int contentfull(byte[] b, int off, int len) throws IOException{
		chunk.flush();
		ByteArrayInputStream in = new ByteArrayInputStream(chunk.toByteArray());
		chunk.reset();
		byte[] back = new byte[0];
		if (len<in.available()){
			back = new byte[in.available()-len];
		}
		int readed = in.read(b,off,len);
		in.read(back);
		in.close();
		chunk.write(back);
		return readed;
	}
	private void sendNext() throws IOException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException{
		while (chunk.toByteArray().length>vmaxSize){
			byte[] steal = new byte[vmaxSize];
			int cin = contentfull(steal,0,vmaxSize);
			writer.write(Security.encrypt(steal, key, vmaxSize));
		}
	}
	public void flush() throws IOException{
		byte[] chunk = new byte[vmaxSize];
		int csize = 0;
		this.chunk.flush();
		ByteArrayInputStream in = new ByteArrayInputStream(this.chunk.toByteArray());
		while ((csize=in.read(chunk))!=-1){
			try{
				writer.write(Security.encrypt(chunk, key, csize));
			}catch(Exception err){}
		}
		in.close();
		this.chunk.reset();
		writer.flush();
	}
	public void close() throws IOException{
		if (chunk.toByteArray().length>0){
			flush();
		}
		chunk.close();
		writer.close();
	}
	public void close_() throws IOException{
		if (chunk.toByteArray().length>0){
			flush();
		}
		chunk.close();
	}
}
